package com.itlong.cloud.operate.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.itlong.cloud.POJO.DTO.operate.OperateUserInfoDTO;
import com.itlong.cloud.POJO.DTO.operate.OperateUserInfoGetPageDTO;
import com.itlong.cloud.POJO.PO.OperateEngineerProjectPO;
import com.itlong.cloud.POJO.PO.OperateUserInfoPO;
import com.itlong.cloud.POJO.VO.MessageVO;
import com.itlong.cloud.POJO.VO.operate.OperateEngineerProjectVO;
import com.itlong.cloud.POJO.VO.operate.OperateLoginErrorCacheVO;
import com.itlong.cloud.POJO.VO.operate.OperateUserInfoGetOneVO;
import com.itlong.cloud.POJO.VO.operate.OperateUserInfoGetUserPageVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.constants.RabbitMQConstant;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.enumerate.AssessSyncDataTypeEnum;
import com.itlong.cloud.enumerate.DataStatusEnum;
import com.itlong.cloud.enumerate.OperateSystemSetUpEnum;
import com.itlong.cloud.enumerate.SystemTypeEnum;
import com.itlong.cloud.enumerate.ecode.OperateErrorCodeEnum;
import com.itlong.cloud.enumerate.ecode.PropertyErrorCodeEnum;
import com.itlong.cloud.operate.dao.IOperateRoleDao;
import com.itlong.cloud.operate.dao.IOperateUserInfoDao;
import com.itlong.cloud.operate.service.IOperateUserInfoService;
import com.itlong.cloud.rabbitmq.config.MessageSender;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.thrown.DataAccessException;
import com.itlong.cloud.utils.data.handler.SqlUtil;
import com.itlong.cloud.utils.encrypt.Md5EncryptUtil;
import com.itlong.cloud.utils.encrypt.UserTokenUtil;
import com.itlong.cloud.utils.page.Page;
import com.itlong.cloud.utils.random.LogicIdUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
 * <desc>
 *      运营-系统-用户信息业务处理接口实现类
 * </desc>
 *
 * @createDate 2017/09/27s
 */
@Service
@RefreshScope
public class OperateUserInfoServiceImpl implements IOperateUserInfoService{

    private static Logger LOG = LoggerFactory.getLogger(OperateUserInfoServiceImpl.class);

    @Autowired
    IOperateUserInfoDao iOperateUserInfoDao;
    @Autowired
    IOperateRoleDao iOperateRoleDao;
    @Autowired
    RedisService<OperateUserInfoPO> redisService;

    //Redis工具接口类
    @Autowired
    private RedisService<OperateLoginErrorCacheVO> loginErrorRedisService;

    @Value("${" + PlatformConstants.OPERATE_USER_DEFAULT_PASSWORD + "}")
    String  userDefaultPassword;
    @Value("${" + PlatformConstants.OPERATE_USER_TOKEN_KEY + "}")
    String userTokenKey;

    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    private Lock writeLock;
    @PostConstruct
    public void init(){
        writeLock = lock.writeLock();
    }

    @Autowired
    MessageSender messageSender;

    String userIdSeparator = "_";
    String dateFormatStr = "yyyy-MM-dd HH:mm:ss";

    /**
     * <desc>
     *      修改密码
     * </desc>
     *
     * @param userName 用户名
     * @param password 密码
     * @param newPassword 新密码
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/13
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public Integer updatePassword(String userName,String password,String newPassword) throws Exception {
        OperateUserInfoPO userInfo=new OperateUserInfoPO();
        userInfo.setUserName(userName);
        userInfo.setPassword(Md5EncryptUtil.md5(password));
        LOG.info("【修改密码前userInfo:】"+JSON.toJSONString(userInfo));
        userInfo=iOperateUserInfoDao.getUserInfoByUserNameAndPassword(userInfo);
        LOG.info("【修改密码后userInfo:】"+JSON.toJSONString(userInfo==null?"":userInfo));
        if(userInfo!=null){
            OperateUserInfoPO user=new OperateUserInfoPO();
            user.setUserId(userInfo.getUserId());
            user.setPassword(Md5EncryptUtil.md5(newPassword));
            user.setPasswordTime(new Date());
            JSONObject jsonObject = new JSONObject();
            user.setSyncType(2);
            jsonObject.put("data",user);
            jsonObject.put("type", AssessSyncDataTypeEnum.USER.getType());
            messageSender.send(RabbitMQConstant.RABBITMQ_ASSESS_SYNC_DATA_QUEUE, jsonObject.toJSONString(),
                    RabbitMQConstant.RABBITMQ_SYNC_DATA_EXCHANGE, RabbitMQConstant.RABBITMQ_ASSESS_SYNC_DATA_KEY);
            return iOperateUserInfoDao.update(SqlUtil.durableData(user,PlatformConstants.TABLE_UPDATE));
        }
        return null;
    }

    /**
     * <desc>
     *      保存人员
     * </desc>
     *
     * @param operateUserInfoPO 人员实体
     * @return
     * @author Jiaqi.X
     * @createDate 2017/09/27
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public Integer save(OperateUserInfoPO operateUserInfoPO) throws Exception {
        int result;
        //验证账号是否存在
        result = iOperateUserInfoDao.checkUserName(operateUserInfoPO.getUserName());
        if (result > 0) {
            return OperateErrorCodeEnum.USERNAME_EXIST.getErrorCode().getSubCode();
        }
        //保存运营角色
        operateUserInfoPO.setUserId(LogicIdUtil.bussinessId());
        operateUserInfoPO.setCreateTime(new Date());
        operateUserInfoPO.setStatus(DataStatusEnum.NORMAL.getType());
        operateUserInfoPO.setPassword(Md5EncryptUtil.md5(userDefaultPassword));
        operateUserInfoPO.setPasswordTime(new Date());
        result = iOperateUserInfoDao.save(SqlUtil.durableData(operateUserInfoPO, PlatformConstants.TABLE_SAVE));
        JSONObject jsonObject = new JSONObject();
        operateUserInfoPO.setSyncType(1);
        //此处为兼容保存用户时去除角色选项，但如所添加用户为工程人员时则需默认其为工程人员角色
        if(StringUtils.isNotEmpty(operateUserInfoPO.getRelationInfo())){
            operateUserInfoPO.setRoleId("1");
        }
        //保存人员角色关系
        String[] roleIds=StringHandlerUtil.splitString(operateUserInfoPO.getRoleId());
        if(roleIds.length>0) {
            Map<String, Object> params = new HashMap<>();
            params.put("userId", operateUserInfoPO.getUserId());
            params.put("roleIds", roleIds);
            params.put("status", DataStatusEnum.NORMAL.getType());
            params.put("createTime", new Date());
            result = iOperateUserInfoDao.saveUserRoles(params);
            for (String roleId : roleIds) {
                if (roleId.equals(OperateSystemSetUpEnum.ENGINNER.getType().toString())) {
                    //添加工程人员与项目之间的关系
                    Date nowTime = new Date();
                    List<OperateEngineerProjectPO> engineerProjectPOS = JSON.parseArray(operateUserInfoPO.getRelationInfo(), OperateEngineerProjectPO.class);
                    for (OperateEngineerProjectPO engineerProjectPO : engineerProjectPOS){
                        engineerProjectPO.setUserId(operateUserInfoPO.getUserId());
                        engineerProjectPO.setStatus(DataStatusEnum.NORMAL.getType());
                        engineerProjectPO.setCreateTime(nowTime);
                        engineerProjectPO.setCreateTime(nowTime);
                    }
                    result = iOperateUserInfoDao.batchSaveEngineerProject(engineerProjectPOS);
                }
            }
            operateUserInfoPO.setSyncRoleIds(operateUserInfoPO.getRoleId());
        }
        jsonObject.put("data",operateUserInfoPO);
        jsonObject.put("type", AssessSyncDataTypeEnum.USER.getType());
        messageSender.send(RabbitMQConstant.RABBITMQ_ASSESS_SYNC_DATA_QUEUE, jsonObject.toJSONString(),
                RabbitMQConstant.RABBITMQ_SYNC_DATA_EXCHANGE, RabbitMQConstant.RABBITMQ_ASSESS_SYNC_DATA_KEY);
        return result;
    }

    /**
     * <desc>
     *      更新人员
     * </desc>
     *
     * @param operateUserInfoPO 人员实体
     * @return
     * @author Jiaqi.X
     * @createDate 2017/09/27
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public Integer update(OperateUserInfoPO operateUserInfoPO) throws Exception {
        OperateUserInfoPO oldUserInfo=iOperateUserInfoDao.getOne(operateUserInfoPO);
        int result;
        //验证账号是否存在
        if(StringUtils.isNotBlank(oldUserInfo.getUserName()) && !oldUserInfo.getUserName().equals(operateUserInfoPO.getUserName())) {
            result = iOperateUserInfoDao.checkUserName(operateUserInfoPO.getUserName());
            if (result > 0) {
                return OperateErrorCodeEnum.USERNAME_EXIST.getErrorCode().getSubCode();
            }
        }
        operateUserInfoPO.setUpdateTime(new Date());
        //更新人员信息
        result=iOperateUserInfoDao.update(SqlUtil.durableData(operateUserInfoPO, PlatformConstants.TABLE_UPDATE));
        String[] roleIds=StringHandlerUtil.splitString(operateUserInfoPO.getRoleId());
        ArrayList<String> list = new ArrayList<String>(Arrays.asList(roleIds)) ;
        //此处为兼容保存用户时去除角色选项，但如所添加用户为工程人员时则需默认其为工程人员角色
        if(StringUtils.isNotEmpty(operateUserInfoPO.getRelationInfo()) && !list.contains("1")){
            list.add("1");
            operateUserInfoPO.setRoleId(StringUtils.join(list.toArray(),','));
        }
        //先将之前的角色关系删除
        iOperateUserInfoDao.deleteUserRoles(operateUserInfoPO.getUserId());
        String[] projectIds = StringHandlerUtil.splitString(operateUserInfoPO.getProjectId());
        //保存人员角色关系
        if(list.size()>0){
            Map<String,Object> params=new HashMap<>();
            params.put("userId",operateUserInfoPO.getUserId());
            params.put("roleIds",list);
            params.put("status",DataStatusEnum.NORMAL.getType());
            params.put("createTime",new Date());
            result=iOperateUserInfoDao.saveUserRoles(params);
            for(String roleId:list){
                if(roleId.equals(OperateSystemSetUpEnum.ENGINNER.getType().toString())){
                    //删除工程人员与项目之间的关系
                    iOperateUserInfoDao.deleteEngineerProjectRelation(operateUserInfoPO.getUserId());
                    //添加工程人员与项目之间的关系
                    Date nowTime = new Date();
                    List<OperateEngineerProjectPO> engineerProjectPOS = JSON.parseArray(operateUserInfoPO.getRelationInfo(), OperateEngineerProjectPO.class);
                    for (OperateEngineerProjectPO engineerProjectPO : engineerProjectPOS){
                        engineerProjectPO.setUserId(operateUserInfoPO.getUserId());
                        engineerProjectPO.setCreateTime(nowTime);
                        engineerProjectPO.setUpdateTime(nowTime);
                        engineerProjectPO.setStatus(DataStatusEnum.NORMAL.getType());
                    }
                    iOperateUserInfoDao.batchSaveEngineerProject(engineerProjectPOS);
                }
            }
            operateUserInfoPO.setSyncRoleIds(operateUserInfoPO.getRoleId());
        }
        JSONObject jsonObject = new JSONObject();
        operateUserInfoPO.setSyncType(2);
        jsonObject.put("data",operateUserInfoPO);
        jsonObject.put("type", AssessSyncDataTypeEnum.USER.getType());
        messageSender.send(RabbitMQConstant.RABBITMQ_ASSESS_SYNC_DATA_QUEUE, jsonObject.toJSONString(),
                RabbitMQConstant.RABBITMQ_SYNC_DATA_EXCHANGE, RabbitMQConstant.RABBITMQ_ASSESS_SYNC_DATA_KEY);
        return result;
    }

    /**
     * <desc>
     *      获取所有人员
     * </desc>
     *
     * @return
     * @author Jiaqi.X
     * @createDate 2017/09/27
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<OperateUserInfoPO> getList() {
        return iOperateUserInfoDao.getList();
    }

    /**
     * <desc>
     *      获取分页数据
     * </desc>
     *
     * @param pageDTO   参数DTO
     * @return
     * @author Jiaqi.X
     * @createDate 2017/09/27
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Page<OperateUserInfoGetUserPageVO> getPage(OperateUserInfoGetPageDTO pageDTO) throws Exception {
        //将DTO转换为Map params
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(pageDTO);
        //分页类默认pageSize为20
        Page<OperateUserInfoGetUserPageVO> page = new Page<>();
        page.getPage().setPageSize(pageDTO.getPageSize());
        page.getPage().setCurrentPage(pageDTO.getCurrentPage());
        params.put("currentPage",page.getPage().getStartSlip());
        params.put("pageSize",page.getPage().getPageSize());
        //填充返回数据集
        page.setRows(iOperateUserInfoDao.getPage(params), iOperateUserInfoDao.getPageCount(params));
        return page;
    }

    /**
     * <desc>
     *      根据id查询人员
     * </desc>
     *
     * @param operateGroupPO 人员实体
     * @return
     * @author Jiaqi.X
     * @createDate 2017/09/27
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public OperateUserInfoPO getOne(OperateUserInfoPO operateGroupPO) {
        return iOperateUserInfoDao.getOne(operateGroupPO);
    }

    /**
     * <desc>
     *      根据id查询人员VO
     * </desc>
     *
     * @param operateUserInfoPO 人员实体
     * @return
     * @author Jiaqi.X
     * @createDate 2017/09/27
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public OperateUserInfoGetOneVO getOneVO(OperateUserInfoPO operateUserInfoPO) throws Exception{
        OperateUserInfoGetOneVO userInfo=iOperateUserInfoDao.getOneForVO(operateUserInfoPO);
        //查询工程人员项目updateUserProject
        Map<String,Object> projectInfo=iOperateUserInfoDao.getEngineerProjectInfo(operateUserInfoPO.getUserId());
        if(projectInfo!=null) {
            userInfo.setProjectName(projectInfo.get("projectName") != null ? projectInfo.get("projectName").toString() : "");
            userInfo.setProjectId(projectInfo.get("projectId") != null ? projectInfo.get("projectId").toString() : "");
            //组装用户项目详情
            if(StringUtils.isNotBlank(userInfo.getProjectId())){
                String[] projectId=StringHandlerUtil.splitString(userInfo.getProjectId());
                String[] projectName=StringHandlerUtil.splitString(userInfo.getProjectName());
                List<Map<String,Object>> projectInfos=new ArrayList<>();
                for(int i = 0 ; i < projectId.length ; i++){
                    Map<String,Object> project=new HashMap<>();
                    project.put("projectId",projectId[i]);
                    project.put("projectName",projectName[i]);
                    projectInfos.add(project);
                }
                userInfo.setProjectInfos(projectInfos);
            }
        }
        return userInfo;
    }

    /**
     * <desc>
     *      删除用户
     * </desc>
     *
     * @param userIds 用户id 多个,号分隔
     * @return sql执行行数
     * @author Jiaqi.X
     * @createDate 2017/09/25
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public Integer delete(String userIds) throws Exception {
        String userId[] = StringHandlerUtil.splitString(userIds);
        List<String> users= Arrays.asList(userId);
        for(int i=users.size()-1 ;i >= 0 ; i--){
            if(users.get(i).equals(OperateSystemSetUpEnum.ADMIN.getType().toString())){
                users.remove(i);
            }else {
                //同时删除缓存内容,否则登陆中的帐号还可以继续使用
                redisService.del(RedisConstant.OPERATE_REDIS_USER_KEY + users.get(i));
                JSONObject jsonObject = new JSONObject();
                OperateUserInfoPO operateUserInfoPO = new OperateUserInfoPO();
                operateUserInfoPO.setStatus(0);
                operateUserInfoPO.setUpdateTime(new Date());
                operateUserInfoPO.setSyncType(3);
                operateUserInfoPO.setUserId(users.get(i));
                jsonObject.put("data",operateUserInfoPO);
                jsonObject.put("type", AssessSyncDataTypeEnum.USER.getType());
                messageSender.send(RabbitMQConstant.RABBITMQ_ASSESS_SYNC_DATA_QUEUE, jsonObject.toJSONString(),
                        RabbitMQConstant.RABBITMQ_SYNC_DATA_EXCHANGE, RabbitMQConstant.RABBITMQ_ASSESS_SYNC_DATA_KEY);
            }
        }
        if(!users.isEmpty()) {
            return iOperateUserInfoDao.delete(users.toArray(new String[users.size()]), new Date());
        }
        return 1;
    }


    /**
     * <desc>
     *      重置用户密码
     * </desc>
     *
     * @param userIds 用户id数组
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/12
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public Integer resetPassword(String userIds) throws Exception {
        String userId[] = StringHandlerUtil.splitString(userIds);
        List<String> users= new ArrayList<>(Arrays.asList(userId));
        for(int i=0;i<users.size();i++){
            if(users.get(i).equals(OperateSystemSetUpEnum.ADMIN.getType().toString())){
                users.remove(i);
            }
        }
        if(users.size() > 0) {
            for(String id:users){
                OperateUserInfoPO user = new OperateUserInfoPO();
                user.setUserId(id);
                user.setPassword(Md5EncryptUtil.md5(userDefaultPassword));
                JSONObject jsonObject = new JSONObject();
                user.setSyncType(2);
                jsonObject.put("data",user);
                jsonObject.put("type", AssessSyncDataTypeEnum.USER.getType());
                messageSender.send(RabbitMQConstant.RABBITMQ_ASSESS_SYNC_DATA_QUEUE, jsonObject.toJSONString(),
                        RabbitMQConstant.RABBITMQ_SYNC_DATA_EXCHANGE, RabbitMQConstant.RABBITMQ_ASSESS_SYNC_DATA_KEY);
            }
            return iOperateUserInfoDao.resetPassword(
                    users.toArray(new String[users.size()]),
                    Md5EncryptUtil.md5(userDefaultPassword),
                    new Date()
            );
        }else{
            return 1;
        }
    }

    /**
     * <desc>
     *      用户登录验证设置缓存信息
     * </desc>
     *
     * @param userInfo 用户实体
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/12
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public OperateUserInfoPO login(OperateUserInfoPO userInfo) throws UnsupportedEncodingException {
        userInfo.setPassword(Md5EncryptUtil.md5(userInfo.getPassword()));
        userInfo=iOperateUserInfoDao.getUserInfoByUserNameAndPassword(userInfo);
        if(userInfo==null){
            return null;
        }
        //设置角色信息
        Map<String,Object> roleInfo=iOperateRoleDao.getUserRoleName(userInfo.getUserId());
        if(roleInfo!=null&&roleInfo.get("roleName")!=null) {
            userInfo.setRoleName(roleInfo.get("roleName").toString());
            userInfo.setRoleId(roleInfo.get("roleId").toString());
        }

        //为了保证异地登录，账号被挤下线的产品效果，现将token设置成与userId相关的动态值
        String token = UserTokenUtil.tokenEncrypt(String.format("%s%s%s",userInfo.getUserId(),userIdSeparator,LogicIdUtil.bussinessId()),
                userTokenKey, SystemTypeEnum.OPERATE.getType());
        userInfo.setToken(token);

        //清除因输入错账号密码的缓存
        String lockUserNameKey = String.format("%s%s", RedisConstant.OPERATE_LOGIN_ERROR_REDIS_KEY, userInfo.getUserId());
        loginErrorRedisService.del(lockUserNameKey);

        /*userInfo.setToken(UserTokenUtil.tokenEncrypt(
                userInfo.getUserId(),userTokenKey, SystemTypeEnum.OPERATE.getType()));*/
        //将用户添加进缓存
        redisService.set(RedisConstant.OPERATE_REDIS_USER_KEY+userInfo.getUserId(),RedisConstant.OPERATE_LOGIN_TIME,userInfo);
        //清空用户权限缓存
        redisService.del(RedisConstant.OPERATE_REDIS_USER_AUTH_KEY + userInfo.getUserId());
        return userInfo;
    }

    /**
     * <desc>
     *      从缓存中获取用户信息
     * </desc>
     *
     * @param token 用户token
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/12
     */
    @Override
    public OperateUserInfoPO retrieve(String token) {
        try {
            if (StringUtils.isBlank(token)) {
                return null;
            }
            //解密拿到userId
            //String userId = UserTokenUtil.tokenDecrypt(token, userTokenKey);
            String userId = UserTokenUtil.tokenDecryptBySSO(token, userTokenKey);
            if (userId == null) {
                return null;
            }
            OperateUserInfoPO userInfoPO = redisService.getObject(RedisConstant.OPERATE_REDIS_USER_KEY + userId, OperateUserInfoPO.class);
            if (userInfoPO != null && token.equals(userInfoPO.getToken())) {

                String desToken = UserTokenUtil.tokenDecryptBySSO(userInfoPO.getToken(), userTokenKey);
                try {
                    if (StringUtils.isNotEmpty(desToken) && userId.equals(desToken.split(URLEncoder.encode(userIdSeparator, "UTF-8"))[0])) {
                        //propertyUserCacheVO.setLastOperateTime(new SimpleDateFormat(dateFormatStr).format(currentTime));
                        redisService.set(RedisConstant.OPERATE_REDIS_USER_KEY + userId, RedisConstant.OPERATE_LOGIN_TIME, userInfoPO);
                    }
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }

                userInfoPO.setIsLongTimeNoOperation(false);
                return userInfoPO;
            }
            if(userInfoPO == null){
                OperateUserInfoPO po = new OperateUserInfoPO();
                po.setIsLongTimeNoOperation(true);
                return po;
            }
            return null;

        }catch (RedisConnectionFailureException e){
            throw new DataAccessException("运营retrieve【从缓存中获取用户信息】redis连接失败") ;
        }
    }

    /**
     * <desc>
     *      从缓存中获取用户信息
     * </desc>
     *
     * @param token 用户token
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/12
     */
    @Override
    public OperateUserInfoPO newRetrieve(String token,String sessionId) {
        try {
            if (StringUtils.isBlank(token)) {
                return null;
            }
            //解密拿到userId
            //String userId = UserTokenUtil.tokenDecrypt(token, userTokenKey);
            String userId = UserTokenUtil.tokenDecryptBySSO(token, userTokenKey);
            if (userId == null) {
                return null;
            }
            OperateUserInfoPO userInfoPO = redisService.getObject(RedisConstant.OPERATE_REDIS_USER_KEY + userId, OperateUserInfoPO.class);
            if (userInfoPO != null && token.equals(userInfoPO.getToken())) {
                String desToken = UserTokenUtil.tokenDecryptBySSO(userInfoPO.getToken(), userTokenKey);
                try {
                    if (StringUtils.isNotEmpty(desToken) && userId.equals(desToken.split(URLEncoder.encode(userIdSeparator, "UTF-8"))[0])) {
                        //propertyUserCacheVO.setLastOperateTime(new SimpleDateFormat(dateFormatStr).format(currentTime));
                        if(StringUtils.isBlank(userInfoPO.getOperateSessionId())){
                            userInfoPO.setOperateSessionId(sessionId);
                        }
                        redisService.set(RedisConstant.OPERATE_REDIS_USER_KEY + userId, RedisConstant.OPERATE_LOGIN_TIME, userInfoPO);
                    }
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }

                userInfoPO.setIsLongTimeNoOperation(false);
                return userInfoPO;
            }
            if(userInfoPO == null){
                OperateUserInfoPO po = new OperateUserInfoPO();
                po.setIsLongTimeNoOperation(true);
                return po;
            }
            return null;

        }catch (RedisConnectionFailureException e){
            throw new DataAccessException("运营retrieve【从缓存中获取用户信息】redis连接失败") ;
        }
    }

    /**
     * <desc>
     *      注销用户
     * </desc>
     *
     * @param token
     * @author Jiaqi.X
     * @createDate 2017/10/12
     */
    @Override
    public void cancel(String token) {
        String userId = UserTokenUtil.tokenDecryptBySSO(token, userTokenKey);
        if (userId != null) {
            OperateUserInfoPO userInfoPO = redisService.getObject(RedisConstant.OPERATE_REDIS_USER_KEY + userId, OperateUserInfoPO.class);
            //删除oss缓存
            redisService.del(RedisConstant.SSO_REDIS_SESSION_ID_KEY+userInfoPO.getMainSessionId());
            //删除子系统缓存
            redisService.del(RedisConstant.OPERATE_REDIS_USER_KEY+userId);
            redisService.del(RedisConstant.ASSESS_REDIS_USER_KEY+userId);
        }
        //删除用户身份信息缓存
        redisService.del(RedisConstant.OPERATE_REDIS_USER_KEY+UserTokenUtil.tokenDecrypt(token,userTokenKey));
        //删除用户的权限缓存
        redisService.del(RedisConstant.OPERATE_REDIS_USER_AUTH_KEY+UserTokenUtil.tokenDecrypt(token,userTokenKey));
    }

    /**
     * <desc>
     *      检查账号是否被锁定
     * <desc/>
     *
     * @param  account  检查的账号
     * @return  标准化响应结果
     * @author Juguang.S
     * @createDate 2018/07/18
     */
    @Override
    public MessageVO getOperateAccountLockDetail(String account) {
        try {

            Map<String, Object> params = new HashMap<>();
            params.put("userName", account);
            List<OperateUserInfoPO> userPOs = iOperateUserInfoDao.getByFields(params);
            if (userPOs ==null || userPOs.isEmpty()) {
                return null;
            }
            OperateUserInfoPO userInfoPO=userPOs.get(0);

            String lockUserNameKey = String.format("%s%s", RedisConstant.OPERATE_LOGIN_ERROR_REDIS_KEY, userInfoPO.getUserId());
            OperateLoginErrorCacheVO errorCacheVO = loginErrorRedisService.getObject(lockUserNameKey, OperateLoginErrorCacheVO.class);
            Map<String,Object> result = new HashMap<>();
            if (errorCacheVO != null) {

                //计算当前时间和锁定时间，如果小于规定的锁定时间，返回相应提示信息
                String lockTimeStr = errorCacheVO.getLockTime();
                if (StringUtils.isNotEmpty(lockTimeStr)) {
                    Date lockTime = new SimpleDateFormat(dateFormatStr).parse(lockTimeStr);
                    long distanceTime = (new Date().getTime() - lockTime.getTime()) / 1000;
                    Long lockLimitTime = PlatformConstants.OPERATE_LOGIN_ERROR_LOCK_TIME;
                    if (distanceTime < lockLimitTime) {
                        //在锁定时间内：返回锁定时间信息
                        result.put("remainTime",((lockLimitTime - distanceTime) / 60) + 1);
                        return new MessageVO(PropertyErrorCodeEnum.PUB_LOGIN_ERROR_ACCOUNT_LOCKED.getErrorCode(), result);
                    } else {
                        //锁定时间已过，清空该账号的错误缓存数据
                        loginErrorRedisService.del(lockUserNameKey);
                    }
                }
            }
            return null;
        } catch (ParseException e) {
            throw new DataAccessException("【物业_getAccountLockDetail】检查账号是否被锁定异常", e);
        }
    }

    /**
     * <desc>
     *      运营登录错误处理
     * <desc/>
     *
     * @param   userInfo    登录用户DTO
     * @return  标准化响应结果
     * @author Juguang.S
     * @createDate 2018/07/18
     */
    @Override
    public MessageVO loginErrorHandler(OperateUserInfoPO userInfo) {

        String account = userInfo.getUserName();
        Map<String, Object> params = new HashMap<>();
        params.put("userName", account);
        List<OperateUserInfoPO> userPOs = iOperateUserInfoDao.getByFields(params);
        if (userPOs == null || userPOs.isEmpty()) {
            return new MessageVO(OperateErrorCodeEnum.PUB_LOGIN_ACCOUNT_IS_NOT_EXIST.getErrorCode());
        }
        String userId = userPOs.get(0).getUserId();

        //最大输入次数
        Integer limitErrorCount = PlatformConstants.OPERATE_LOGIN_MAX_ERROR_COUNT;
        Map<String, Object> result = new HashMap<>();
        String errorCacheKey = String.format("%s%s", RedisConstant.OPERATE_LOGIN_ERROR_REDIS_KEY, userId);
        OperateLoginErrorCacheVO errorCacheVO = loginErrorRedisService.getObject(errorCacheKey, OperateLoginErrorCacheVO.class);

        if (errorCacheVO == null) {
            //如果该账号之前没有输入错误，添加登陆错误缓存信息，记录输错次数
            errorCacheVO = new OperateLoginErrorCacheVO(account,userId, 1);
            loginErrorRedisService.set(errorCacheKey, RedisConstant.OPERATE_LOGIN_ERROR_TIME, errorCacheVO);
            result.put("errorCount", limitErrorCount - 1);
            return new MessageVO(PropertyErrorCodeEnum.PUB_ACCOUNT_PASSWORD_ERR.getErrorCode(), result);
        } else {

            //查询已经错误的次数：如果次数大于5，锁定30分钟
            Integer errorCount = errorCacheVO.getErrorCount();
            if (errorCount + 1 >= limitErrorCount) {

                //生成账号锁定缓存信息
                String lockUserNameKey = String.format("%s%s", RedisConstant.OPERATE_LOGIN_ERROR_REDIS_KEY, userId);
                errorCacheVO = new OperateLoginErrorCacheVO(account,userId, errorCount);
                errorCacheVO.setLockTime(new SimpleDateFormat(dateFormatStr).format(new Date()));
                loginErrorRedisService.set(lockUserNameKey, RedisConstant.OPERATE_LOGIN_ERROR_TIME, errorCacheVO);
                result.put("remainTime", PlatformConstants.OPERATE_LOGIN_ERROR_LOCK_TIME / 60);
                return new MessageVO(PropertyErrorCodeEnum.PUB_LOGIN_ERROR_ACCOUNT_LOCKED.getErrorCode(), result);
            } else {

                //输错次数小于5次，更新缓存信息，并给出相应提示
                errorCacheVO = new OperateLoginErrorCacheVO(account,userId, errorCount + 1);
                loginErrorRedisService.set(errorCacheKey, RedisConstant.OPERATE_LOGIN_ERROR_TIME, errorCacheVO);
                result.put("errorCount", limitErrorCount - errorCount - 1);
                return new MessageVO(PropertyErrorCodeEnum.PUB_ACCOUNT_PASSWORD_ERR.getErrorCode(), result);
            }
        }
    }

    /**
     * <desc>
     *      判断原密码是否正确
     * <desc/>
     *
     * @param   userId
     * @param   oldPassword
     * @return  标准化响应结果
     * @author Juguang.S
     * @createDate 2019/03/31
     */
    @Override
    public List<OperateUserInfoPO> isUserOldPsdExist(String userId, String oldPassword) {
        Map<String,Object> params = new HashMap<>();
        params.put("userId",userId);
        params.put("password",oldPassword);
        return iOperateUserInfoDao.getByFields(params);
    }

    /**
     * <desc>
     *      用户所属角色是否是工程部管理员
     * <desc/>
     * @param   userId
     * @return  标准化响应结果
     * @author Juguang.S
     * @createDate 2020/07/06
     */
    @Override
    public Integer isEngineerManage(String userId) {
        return iOperateUserInfoDao.isEngineerManage(userId);
    }

    /**
     * <desc>
     *      获取用户信息
     * </desc>Excel
     *
     * @param userName 用户名
     * @return
     * @Author Zhu.yj
     * @createDate  2020/8/25
     */
    @Override
    public OperateUserInfoPO getUserByUserName(String userName) throws Exception {
        return iOperateUserInfoDao.getUserByUserName(userName);
    }

    /**
     * <desc>
     *      获取工程人员项目列表
     * </desc>
     *
     * @return
     * @Author Zhu.yj
     * @createDate  2021/2/1
     */
    @Override
    public List<OperateEngineerProjectVO> getEngineerProjectList(OperateUserInfoDTO operateUserInfoDTO) throws Exception {
        if (StringUtils.isBlank(operateUserInfoDTO.getOrderColumn()) || StringUtils.isBlank(operateUserInfoDTO.getOrderRule())){
            operateUserInfoDTO.setOrderColumn("days");
            operateUserInfoDTO.setOrderRule("DESC");
        }
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(operateUserInfoDTO);
        return iOperateUserInfoDao.getEngineerProjectList(params);
    }

}
